/**
  ******************************************************************************
  * File Name          : CAN.c
  * Description        : This file provides code for the configuration
  *                      of the CAN instances.
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2018 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "can.h"

#include "gpio.h"

/* USER CODE BEGIN 0 */
Data datRx;
Data datTx;

CAN_HandleTypeDef hcan;
extern uint8_t FLAG_EMERGENCY_BRAKING;
extern uint8_t FLAG_START;
extern uint8_t FLAG_STOP;
extern uint16_t MOTOR_ID;
extern uint8_t FLAG_BACE;
extern uint8_t FLAG_2S;

extern int L_Height;
extern int R_Height;
extern int Sport_Mode;
extern int Power;
extern int Set_low;
extern int Set_high;
extern int Set_Power;


extern S_m mode;
/* USER CODE END 0 */

CAN_HandleTypeDef hcan;

/* CAN init function */
void MX_CAN_Init(void)
{

  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 12;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SJW = CAN_SJW_1TQ;
  hcan.Init.BS1 = CAN_BS1_2TQ;
  hcan.Init.BS2 = CAN_BS2_3TQ;
  hcan.Init.TTCM = DISABLE;
  hcan.Init.ABOM = DISABLE;
  hcan.Init.AWUM = DISABLE;
  hcan.Init.NART = DISABLE;
  hcan.Init.RFLM = DISABLE;
  hcan.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    __HAL_RCC_CAN1_CLK_ENABLE();
  
    /**CAN GPIO Configuration    
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* CAN1 interrupt Init */
    HAL_NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{

  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspDeInit 0 */

  /* USER CODE END CAN1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_CAN1_CLK_DISABLE();
  
    /**CAN GPIO Configuration    
    PA11     ------> CAN_RX
    PA12     ------> CAN_TX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);

    /* CAN1 interrupt Deinit */
    HAL_NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
  /* USER CODE BEGIN CAN1_MspDeInit 1 */

  /* USER CODE END CAN1_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */

void CAN_Decode(uint8_t *raw, Data *dat)
{
  dat->Cmd = *(uint16_t *)&raw[0];
  dat->Content = *(int32_t *)&raw[2];
}

void CAN_Encode(uint8_t *raw, Data *dat)
{
  *(uint16_t *)&raw[0] = dat->Cmd;
  *(int32_t *)&raw[2] = dat->Content;
}

void CAN_LoadDataFrame(uint32_t canid, uint16_t cmd, int32_t content)
{
  hcan.pTxMsg->StdId = canid;
  hcan.pTxMsg->RTR = CAN_RTR_DATA;
  hcan.pTxMsg->IDE = CAN_ID_STD;
  hcan.pTxMsg->DLC = 6;

  datTx.CanId = canid;
  datTx.Cmd = cmd;
  datTx.Content = content;
  CAN_Encode(hcan.pTxMsg->Data, &datTx);
}

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *hc)
{
  datRx.CanId = hc->pRxMsg->StdId;
  CAN_Decode(hc->pRxMsg->Data, &datRx);

  FLAG_CAN = HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);


	//Right motor receive can message from Left motor
  if (MOTOR_ID == R_MOTOR_ID)
  {
    if (datRx.CanId == L_MOTOR_ID)
    {
      switch (datRx.Cmd)
      {
      case CMD_HEIGHT:
      {
        L_Height = datRx.Content;
      }
      break;
      case CMD_START:
      {
        if (datRx.Content == 1)
        {
          FLAG_START = 1;
          if (Sport_Mode == HIGHDROP_MODE)
            flag = F_END;
          if (Sport_Mode == FLATBENCHPRESS_MOED)
            flag = F_END;
        }

        if (datRx.Content == 2)
          flag = F_START;
      }
      break;
      case CMD_SAFE:
      {
        if (datRx.Content == 1)
          FLAG_EMERGENCY_BRAKING = 1;
      }
      break;
      case CMD_BACK:
      {
        if (datRx.Content == 0x0001)
        {
          flag = F_NONE;
			    get_height = 0;
					FLAG_START = 0;
					FLAG_2S = 0;
					Power = Power_Value;
        }
      }
      break;
      }
    }
  }

	
	//Left motor receive can message from right motor
  if (MOTOR_ID == L_MOTOR_ID)
  {
    if (datRx.CanId == R_MOTOR_ID)
    {
      switch (datRx.Cmd)
      {
				case CMD_HEIGHT:
				{
					R_Height = datRx.Content;
				}
				break;
				case CMD_START:
				{
					 if (datRx.Content == 1)
					{
						FLAG_START = 1;
						if (Sport_Mode == HIGHDROP_MODE)
							flag = F_END;
						if (Sport_Mode == FLATBENCHPRESS_MOED)
							flag = F_END;
					}

					if (datRx.Content == 2)
						flag = F_START;

				}
				break;
				case CMD_SAFE:
				{
					if (datRx.Content == 1)
						FLAG_EMERGENCY_BRAKING = 1;
				}
				break;
				case CMD_BACK:
				{
					if (datRx.Content == 0x0001)
					{
						 flag = F_NONE;
						 get_height = 0;
						 FLAG_START = 0;
						 FLAG_2S = 0;
						 Power = Power_Value;
					}
				}
				break;
      }
    }
  }

  if (datRx.CanId == 0)
  {
    switch (datRx.Cmd)
    {
    case SetMode:
    {
      mode = M_SetMode;
      switch (datRx.Content)
      {
      case DeadLife:
        Sport_Mode = HARDPULL_MODE;
        break;
      case Squat:
        Sport_Mode = DEEPSQUART_MODE;
        break;
      case PullDown:
        Sport_Mode = HIGHDROP_MODE;
        break;
      case Row:
        Sport_Mode = ROW_MODE;
        break;
      case Stop:
        Sport_Mode = STOP_MODE;
        break;
			default :
				Error_Handler();
      }
    }
    break;
    case SetForce:
    {
      mode = M_SetForce;
      Power = datRx.Content * 20;
			if(Power < 0 || Power > 1200)
			  Error_Handler();
    }
    break;
    case SetPosH:
    {
      mode = M_SetPosH;
      Set_high = datRx.Content;
			if(Set_high < 30 || Set_high > 200)
			  Error_Handler();
    }
    break;
    case SetPosL:
    {
      mode = M_SetPosL;
      Set_low = datRx.Content;
			if(Set_low < 30 || Set_low > 100)
			  Error_Handler();
    }
    break;
    }
  }
	
	
}


void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
	

}

//

/* USER CODE END 1 */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
